﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlurentFiltration;
using FlurentFiltration.Exceptions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace FrameworkUnitTests
{
    [TestClass]
    public class FilteringApiTests
    {
        private const int ChildResultSize = 3;
        private const int ParentResultSize = 1;

        private static IEnumerable<StubObject> CreateCollection()
        {
            return new List<StubObject>
                {
                    new StubObject(),
                    new StubObject(),
                    new StubObject()
                };
        }

        [TestMethod]
        public void TestFluirentFiltration_SuccessFiltered()
        {
            IEnumerable<StubObject> collection = CreateCollection();

            Filter.Reset();
            Filter.Bind<IEnumerable<string>, StringFilterStub>()
                  .Bind<IEnumerable<StubObject>, ComplexFilterStub>();

            var result = collection.Filtrate(new ComplexFilterStub());

            Assert.IsNotNull(result);
            Assert.AreEqual(result.Count(),ParentResultSize);
            Assert.AreEqual(result.FirstOrDefault().Collection1.Count(), ChildResultSize);
            Assert.AreEqual(result.FirstOrDefault().Collection2.Count(), ChildResultSize);
        }

        [TestMethod]
        [ExpectedException(typeof(UnsupportedCollectionTypeException))]
        public void TestFluirentFiltration_IncorrectCollectionType()
        {
            IEnumerable<StubObject> collection = CreateCollection();

            Filter.Reset();
            Filter.Bind<IEnumerable<string>, StringFilterStub>()
                  .Bind<IEnumerable<StubObject>, ComplexFilterStub>();

            var filter = new ComplexFilterStub
                {
                    StringFilter = new ExceptionStringFilterStub()
                };

            collection.Filtrate(filter);
        }


        public class StringFilterStub : IFilter
        {
            public virtual IEnumerable<object> Filtrate(IEnumerable<object> source)
            {
                var collection = source as IEnumerable<string>;
                return collection.Take(ChildResultSize);
            }
        }

        public class ExceptionStringFilterStub : StringFilterStub
        {
            public override IEnumerable<object> Filtrate(IEnumerable<object> source)
            {
                return source.Take(ChildResultSize);
            }
        }

        public class ComplexFilterStub : IFilter
        {
            public ComplexFilterStub()
            {
                StringFilter = new StringFilterStub();
            }

            public IEnumerable<object> Filtrate(IEnumerable<object> source)
            {
                return new List<StubObject> { source.Take(ParentResultSize).FirstOrDefault() as StubObject };
            }

            public StringFilterStub StringFilter { get; set; }
        }

        public class StubObject
        {
            public IEnumerable<string> Collection1 { get; set; }
            public IEnumerable<string> Collection2 { get; set; }

            public StubObject()
            {
                Collection1 = new List<string>
                {
                    "aaa","bbb","ccc","ddd","eee"
                };
                Collection2 = new List<string>
                {
                    "AAA","BBB","CCC","DDD","EEE"
                };
            }
        }
    }

   
}
